/* BooleanType.js
 *
 * Copyright 2006, Tim Dwelle.
 *
 * Licensed under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of
 * the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See
 * the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

$package("dowry.datatype");

/**
 * Object representation of a boolean datatype.
 *
 */
$class("BooleanType").$extends("Datatype").$as(
{
    /**
     * Constant for the error message when validation finds
     * value other than true or false.
     *
     */
    ERROR_NOT_A_BOOLEAN : Dowry.msgs.getMessage("ERROR_NOT_A_BOOLEAN"),

    /**
     * Constant for the string representation of boolean
     * false.
     *
     */
    FALSE : Dowry.msgs.getMessage("false"),

    /**
     * Constant for the string representation of boolean
     * true.
     *
     */
    TRUE : Dowry.msgs.getMessage("true"),

    /**
     * Extends Datatype's <code>toConfiguration()</code> to
     * include the extra properties <code>maxLength</code>
     * and <code>validChars</code>.  These properties are
     * included for use by interested widgets.
     *
     * @param  id    the identifier for the field associated
     *               with this datatype (optional)
     *
     * @param  val   the field value associated with this
     *               datatype (optional)
     *
     * @return       an object containing the datatype
     *               information as a map
     *
     */
    toConfiguration : function(id, val)
    {
        var cfg = this.$super(arguments);

        // max length
        cfg.maxLength = this.FALSE.length;
        if (this.TRUE.length > this.FALSE.length)
        {
            cfg.maxLength = this.TRUE.length;
        }

        // valid characters
        cfg.validChars = this.TRUE + this.FALSE;

        return cfg;
    },

    /**
     * Converts some raw value to a value of the appropriate
     * datatype.
     *
     * @param val  the original, raw value representation
     *
     * @return     the value converted to the appropriate
     *             datatype
     *
     */
    toDatatype : function(val)
    {
        if (typeof val != "boolean" &&
            val != null)
        {
            if (val == this.TRUE)
            {
                val = true;
            }
            else if (val == this.FALSE)
            {
                val = false;
            }
            else
            {
                val = null;
            }
        }

        return val;
    },

    /**
     * Converts some value of the appropriate datatype to
     * a string representation.
     *
     * @param val  the original value of the appropriate
     *             datatype
     *
     * @return     the value converted to a string
     *
     */
    toFormattedString : function(val)
    {
        var s = null;

        // boolean
        if (typeof val == "boolean")
        {
            if (val)
            {
                s = this.TRUE;
            }
            else
            {
                s = this.FALSE;
            }
        }

        // literal... this looks wierd, but
        // its to ensure that js loose typing
        // isn't giving us back a non-string
        else if (val == this.TRUE)
        {
            s = this.TRUE;
        }
        else if (val == this.FALSE)
        {
            s = this.FALSE;
        }

        return s;
    },


    /**
     * Validates that:
     *
     * <ol>
     *  <li>  the value is provided, if required as
     *        specified by map key <code>required</code>
     *  </li>
     *  <li>  the value represents <code>true</code> or
     *        <code>false</code>
     *  </li>
     * </ol>
     *
     * @param val    a value representation to be validated
     *
     * @return       the string error message, if the
     *               input is invalid; otherwise, null
     *
     */
    validate : function(val)
    {
        // call super.validate()...
        var msg = this.$super(arguments);

        if (msg == null &&
            val != null)
        {
            // compare to the literal string to
            // avoid unwanted type coersion
            val = String(val);
            if (val != this.TRUE && val != this.FALSE)
            {
                msg = this.ERROR_NOT_A_BOOLEAN;
            }
        }

        return msg;
    }
});